// 接口的返回值可能是统一的
// 泛型来创建可重用的组件，一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件。

// 类型变量<T>
interface APIResponse<T> {
    error:number,
    data:T,
    message?:string
}
interface LoginInfo {
    username:string,
    token:string
}

function login():APIResponse<LoginInfo> {
    return {
        error: 1,
        data:{
            username:'张三',
            token:'xxx'
        },
        message:'成功'
    }
}

let r = login()


function loggingIdentity<T>(arg: T[]):T[] {
    console.log('arg.length');
    return arg
}

function identity<T>(arg: T):T {
    return arg
}

let myIdentity: <U>(arg: U) => U = identity
let jj: {<T>(arg:T):T}  // 签名的对象字面量来定义泛型函数

// 在平时开发中我们想使用联合类型
type IUnion<T = boolean> = T |string | number
type t1 = IUnion
type t2 = IUnion<string[] | number[]>
// 泛型是用户传递的类型(用户随便传?)  在使用泛型的时候 都要添加约束 泛型约束

// 我们在使用泛型的时候 不能直接做运算(无法保证泛型的结果 T+T = T)

// 约束当前这个类型T 需要是 string | number 子类型
function getVal<T extends string | number>(val:T):T {
    return val
}

getVal('123')
getVal(123)
// getVal(true)  // 因为类型不满足

function getLen<T extends {length:number}>(val: T){
    return val.length
}
getLen('123')
getLen({length:123})

let person = { name:'jw',age:30 }
function getObjVal<T extends object, K extends keyof T>(target:T,key:K){
    return target[key]
}
getObjVal(person,'name')
export {}